package com.gene.tlonpo.guard.context;

import com.alibaba.fastjson.JSON;
import com.gene.tlonpo.exception.TlonpoException;
import com.gene.tlonpo.util.AssertUtil;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

import javax.servlet.AsyncContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * 长轮训异步包装上下文
 *
 * @author gene
 * 支持dubbo和servlet
 */
public class AsynContext {
    private org.apache.dubbo.rpc.AsyncContext dubboContext;

    private AsyncContext servletContext;

    public AsynContext(org.apache.dubbo.rpc.AsyncContext dubboContext) {
        if (Objects.isNull(dubboContext)) {
            throw new RuntimeException("AsynContext instance fail,dubboContext can not be null");
        }
        this.dubboContext = dubboContext;
    }

    public AsynContext(AsyncContext servletContext) {
        if (Objects.isNull(servletContext)) {
            throw new RuntimeException("AsynContext instance fail,servletContext can not be null");
        }
        this.servletContext = servletContext;
    }

    /**
     * 数据写回
     *
     * @param data
     * @throws IOException
     */
    public void write(Object data) throws IOException {

        if (Objects.isNull(data)) {
            return;
        }

        writeForDubbo(data);

        writeForServlet(data);
    }

    /**
     * 写回servlet数据
     *
     * @param data
     */
    private void writeForServlet(Object data) throws IOException {
        if (servletContext != null) {
            servletContext.getResponse().getWriter().write(JSON.toJSONString(data));
            servletContext.complete();
        }
    }

    /**
     * 写回dubbocontext数据
     *
     * @param data
     */
    private void writeForDubbo(Object data) {
        if (dubboContext != null) {
            dubboContext.write(data);
        }

    }

    public static AsyncContext startServletAsync(ServletRequest request, ServletResponse response) {
        AssertUtil.isNotNull(request);
        AssertUtil.isNotNull(response);
        if (request.isAsyncSupported()) {
            AsyncContext asyncContext = request.startAsync(request, response);
            //设置默认编码和content-type
            asyncContext.getResponse().setCharacterEncoding(String.valueOf(StandardCharsets.UTF_8));
            asyncContext.getResponse().setContentType("application/json;charset=utf-8");
            return asyncContext;
        } else {
            throw new TlonpoException("current servlet can not support async");
        }
    }


}
